package com.treasure.mall.biz.service.core.order.impl;

import com.treasure.mall.biz.base.AbstractSearchableCrudService;
import com.treasure.mall.biz.base.SpecificationAndSort;
import com.treasure.mall.biz.dto.BaseSaveDTO;
import com.treasure.mall.biz.dto.BaseSearchDTO;
import com.treasure.mall.biz.entity.embeddable.Product;
import com.treasure.mall.biz.entity.order.OrderItemPO;
import com.treasure.mall.biz.entity.order.SettlementBillPO;
import com.treasure.mall.biz.entity.order.SubOrderPO;
import com.treasure.mall.biz.repository.order.SettlementBillRepository;
import com.treasure.mall.biz.service.core.order.SettlementBillService;
import com.treasure.mall.biz.service.core.order.SubOrderService;
import com.treasure.mall.biz.service.core.user.MerchantService;
import com.treasure.mall.zbq.common.MathUtils;
import com.treasure.mall.zbq.common.RandomUtils;
import com.treasure.mall.zbq.common.base.ApiResult;
import com.treasure.mall.zbq.common.exception.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.List;

/**
 * @author allan
 * @version 1.0.0
 * @date 2020/7/23
 */
@Service
@Slf4j
public class SettlementBillServiceImpl extends AbstractSearchableCrudService<SettlementBillPO, String> implements SettlementBillService {
    private SettlementBillRepository billRepository;
    @Autowired
    private MerchantService merchantService;

    @Autowired
    private SubOrderService subOrderService;

    @Autowired
    protected SettlementBillServiceImpl(SettlementBillRepository repository) {
        super(repository);
        this.billRepository = repository;
    }

    @Override
    protected SpecificationAndSort<SettlementBillPO> specificationAndSort(BaseSearchDTO searchDTO) {
        return null;
    }

    @Override
    public SettlementBillPO save(BaseSaveDTO saveDTO) {
        return null;
    }

    @Override
    public SettlementBillPO create(OrderItemPO orderItemPO) {
        SettlementBillPO po = new SettlementBillPO();
        po.setId(RandomUtils.randomFlowNo());
        po.setOrderItemId(orderItemPO.getId());
        po.setSubOrderId(orderItemPO.getSubOrderPO().getSubOrderId());
        po.setProduct(new Product(orderItemPO.getGoodsInfo()));
        po.setServiceRate(orderItemPO.getGoodsInfo().getServiceRate());
        //货款=销售价*数量-返利基数
        BigDecimal rebateBase = orderItemPO.getGoodsInfo().getServiceRate()
                .multiply(orderItemPO.goodsAmount()).divide(BigDecimal.valueOf(100), RoundingMode.HALF_UP);
        po.setAmount(orderItemPO.goodsAmount().subtract(rebateBase));
        if (MathUtils.greater(po.getAmount(), BigDecimal.ZERO)) {
            po.setMerchantPO(orderItemPO.getSubOrderPO().getMerchantPO());

            return save(po);
        }
        return null;
    }

    @Override
    public List<SettlementBillPO> findBySubOrder(String subOrderId) {
        return billRepository.findBySubOrderId(subOrderId);
    }

    @Override
    public SettlementBillPO findByOrderItem(Long orderItemId) {
        return billRepository.findByOrderItemId(orderItemId);
    }

    @Override
    public List<SettlementBillPO> findToConvert() {
        return billRepository.findByInvalidateIsFalseAndConvertedIsFalseAndConvertTimeLessThanEqual(LocalDateTime.now());
    }

    @Override
    @Transactional
    public void convert(SettlementBillPO po) {
        if (po.isInvalidate() || po.isConverted()) {
            throw new ApiException(ApiResult.error("当前单据已失效或者已转正"));
        }

        SubOrderPO subOrderPO = subOrderService.findById(po.getSubOrderId());
        //检查是否能转正
        if (subOrderPO == null || !subOrderPO.isCanConverted()) {
            throw new ApiException(ApiResult.error("订单售后中，无法转正"));
        }

        //转正货款
        merchantService.settlePayment(po.getMerchantPO().getId(), po.getAmount(), po.getSubOrderId());

        po.setConverted(true);
        save(po);
    }

    /**
     * 修改结算单是否失效
     * 产生售后行为时，设置为失效true，售后拒绝或取消售后设置为false
     *
     * @param orderItemId
     * @param invalidate
     */
    @Override
    public void modifyInvalidate(Long orderItemId, boolean invalidate) {
        billRepository.modifyInvalidate(orderItemId, invalidate);
    }

}
